import { computed, inject, reactive, Ref, ref } from 'vue'
import { Widget } from '@/models'
import { PageData, Viewer } from '@/types'
import { Keys } from '../contract/hotkey/types'
import { GLOBAL_KEYBOARD } from '../contract/hotkey/useHotkey'
import { useDrag } from '@/utils'

/** 框选 */
export default function useBoxSelection(
  /** 页面信息 */
  page: Ref<PageData>,

  /** 当前页控件 */
  widgets: Ref<Widget[]>
) {
  /** 合同控件 */
  const viewer = inject('Viewer') as Viewer

  /** 是否可见 */
  const visible = ref(false)

  /** 本页是否启用 */
  const enabled = computed(() => widgets.value.some(item => !item.isFixed))

  /** 初始范围 */
  const DEFAULT_RANGE = {
    x0: 0,
    y0: 0,
    x1: 0,
    y1: 0
  }

  /** 框选范围 */
  const range = reactive({ ...DEFAULT_RANGE })

  /** 清理范围 */
  function clearRange() {
    Object.assign(range, DEFAULT_RANGE)
  }

  /** 选择 */
  const select = useDrag({
    onStart(e) {
      const { offsetX: startX, offsetY: startY } = e
      const { w: pw, h: ph } = page.value
      const { lastActiveWidget, selection } = viewer

      clearRange()

      // 没按下 Ctrl 键则清除选中
      if (![Keys.Control, Keys.Command].includes(GLOBAL_KEYBOARD.key as Keys)) {
        selection.clear()
      } else if (lastActiveWidget) {
        selection.add(lastActiveWidget)
      }

      viewer.activeWidgetId = ''

      visible.value = true

      return {
        startX,
        startY,
        pw,
        ph,
        zoom: viewer.zoom.level
      }
    },

    onMoving(e, { x: moveX, y: moveY }, { startX, startY, pw, ph, zoom }) {
      const currentX = startX + moveX / zoom
      const currentY = startY + moveY / zoom

      Object.assign(range, {
        x0: Math.max(0, Math.min(currentX, startX)),
        y0: Math.max(0, Math.min(currentY, startY)),
        x1: Math.min(pw, Math.max(currentX, startX)),
        y1: Math.min(ph, Math.max(currentY, startY))
      } as typeof range)
    },

    onEnd() {
      const { selection } = viewer
      visible.value = false

      widgetsInRange.value.forEach(selection.toggle)

      selection.lock()

      clearRange()
    }
  })

  /** 框选范围内的控件 */
  const widgetsInRange = computed(() => {
    const { x0, y0, x1, y1 } = range

    return widgets.value.filter(
      ({ x, y, w, h, isFixed }) => !isFixed && x + w >= x0 && x <= x1 && y + h >= y0 && y <= y1
    )
  })

  return reactive({
    /** 是否可见 */
    visible: computed(() => {
      const { x0, x1 } = range
      return visible.value && !(x0 === 0 && x1 === 0)
    }),

    /** 本页是否启用 */
    enabled,

    /** 框选范围 */
    range,

    /** 框选样式 */
    style: computed(() => {
      const { x0, y0, x1, y1 } = range

      return {
        width: `${x1 - x0}px`,
        height: `${y1 - y0}px`,
        transform: `translate(${x0}px, ${y0}px)`
      }
    }),

    /** 框选开始 */
    start(e: MouseEvent) {
      if (!(e.target as HTMLElement)?.className?.includes?.('fa-widget-area') || !enabled.value) return

      select.dragStart(e)
    },

    /** 控件是否选择中 */
    isWidgetInRange(widget: Widget) {
      return widgetsInRange.value.includes(widget)
    }
  })
}
